//
//  AmapManger.m
//  jiaKaoZhuShou
//
//  Created by 金艺社 on 2018/5/14.
//  Copyright © 2018年 金艺社. All rights reserved.
//

#import "AmapManger.h"
#import "GeocodeAnnotation.h"
#import "CommonUtility.h"
#define AMAPKEY @"03456db40b1f4864ab210e7f561f342c"
#define DefaultLocationTimeout  6
#define DefaultReGeocodeTimeout 3
@interface AmapManger ()<AMapLocationManagerDelegate, MAMapViewDelegate, AMapSearchDelegate>
@property (nonatomic, strong) AMapLocationManager *locationManager;
@property (nonatomic, copy) AMapLocatingCompletionBlock completionBlock;
@end

@implementation AmapManger {
    NSMutableArray *poiAnnotations;
}
static AmapManger *_instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    // 由于alloc方法内部会调用allocWithZone: 所以我们只需要保证在该方法只创建一个对象即可
    dispatch_once(&onceToken,^{
        // 只执行1次的代码(这里面默认是线程安全的)
        _instance = [super allocWithZone:zone];
        
    });
    return _instance;
}

- (void)addToViewWithView:(UIView *)view {
    ///地图需要v4.5.0及以上版本才必须要打开此选项（v4.5.0以下版本，需要手动配置info.plist）
    [AMapServices sharedServices].enableHTTPS = YES;
    ///设置appKey
    [AMapServices sharedServices].apiKey = AMAPKEY;
    ///初始化地图
    _mapView = [[MAMapView alloc] initWithFrame:view.bounds];
    _mapView.delegate = self;
    //搜索
    self.search = [[AMapSearchAPI alloc] init];
    self.search.delegate = self;
    ///把地图添加至view
    [view addSubview:_mapView];
    [self initCompleteBlock];
    ///如果您需要进入地图就显示定位小蓝点，则需要下面两行代码
    _mapView.showsUserLocation = YES;
    _mapView.userTrackingMode = MAUserTrackingModeFollow;
    
    [self configLocationManager];
    [self reGeocodeAction];
}

- (void)configLocationManager
{
    self.locationManager = [[AMapLocationManager alloc] init];
    [self.locationManager setDelegate:self];
    //设置期望定位精度
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyHundredMeters];
    //设置不允许系统暂停定位
    [self.locationManager setPausesLocationUpdatesAutomatically:NO];
    //设置允许在后台定位
//    [self.locationManager setAllowsBackgroundLocationUpdates:YES];
    //设置定位超时时间
    [self.locationManager setLocationTimeout:DefaultLocationTimeout];
    //设置逆地理超时时间
    [self.locationManager setReGeocodeTimeout:DefaultReGeocodeTimeout];
    //设置开启虚拟定位风险监测，可以根据需要开启
    [self.locationManager setDetectRiskOfFakeLocation:NO];
}

- (void)locAction
{
    [self.mapView removeAnnotations:self.mapView.annotations];
    //进行单次定位请求
    [self.locationManager requestLocationWithReGeocode:NO completionBlock:self.completionBlock];
}

- (void)reGeocodeAction
{
    [self.mapView removeAnnotations:self.mapView.annotations];
    //进行单次带逆地理定位请求
    [self.locationManager requestLocationWithReGeocode:YES completionBlock:self.completionBlock];
}

- (void)cleanUpAction
{
    //停止定位
    [self.locationManager stopUpdatingLocation];
    [self.locationManager setDelegate:nil];
    [self.mapView removeAnnotations:self.mapView.annotations];
}

#pragma mark - Initialization 定位回调
- (void)initCompleteBlock
{
    __weak AmapManger *weakSelf = self;
    self.completionBlock = ^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error)
    {
        if (error != nil && error.code == AMapLocationErrorLocateFailed)
        {
            //定位错误：此时location和regeocode没有返回值，不进行annotation的添加
            NSLog(@"定位错误:{%ld - %@};", (long)error.code, error.localizedDescription);
            return;
        }
        else if (error != nil
                 && (error.code == AMapLocationErrorReGeocodeFailed
                     || error.code == AMapLocationErrorTimeOut
                     || error.code == AMapLocationErrorCannotFindHost
                     || error.code == AMapLocationErrorBadURL
                     || error.code == AMapLocationErrorNotConnectedToInternet
                     || error.code == AMapLocationErrorCannotConnectToHost))
        {
            //逆地理错误：在带逆地理的单次定位中，逆地理过程可能发生错误，此时location有返回值，regeocode无返回值，进行annotation的添加
            NSLog(@"逆地理错误:{%ld - %@};", (long)error.code, error.localizedDescription);
        }
        else if (error != nil && error.code == AMapLocationErrorRiskOfFakeLocation)
        {
            //存在虚拟定位的风险：此时location和regeocode没有返回值，不进行annotation的添加
            NSLog(@"存在虚拟定位的风险:{%ld - %@};", (long)error.code, error.localizedDescription);
            return;
        }
        else
        {
            //没有错误：location有返回值，regeocode是否有返回值取决于是否进行逆地理操作，进行annotation的添加
        }
        
        //根据定位信息，添加annotation
        MAPointAnnotation *annotation = [[MAPointAnnotation alloc] init];
        [annotation setCoordinate:location.coordinate];
        
        //有无逆地理信息，annotationView的标题显示的字段不一样
        if (regeocode)
        {
            weakSelf.infoBlock(regeocode);
            [annotation setTitle:[NSString stringWithFormat:@"%@", regeocode.formattedAddress]];
            [annotation setSubtitle:[NSString stringWithFormat:@"%@-%@-%.2fm", regeocode.citycode, regeocode.adcode, location.horizontalAccuracy]];
        }
        else
        {
            [annotation setTitle:[NSString stringWithFormat:@"lat:%f;lon:%f;", location.coordinate.latitude, location.coordinate.longitude]];
            [annotation setSubtitle:[NSString stringWithFormat:@"accuracy:%.2fm", location.horizontalAccuracy]];
        }
        //存储定位坐标
        NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
        NSArray *ary = @[[NSString stringWithFormat:@"%.6f", location.coordinate.latitude], [NSString stringWithFormat:@"%.6f", location.coordinate.longitude]];
        [user setObject:ary forKey:@"currentPoint"];
        [user synchronize];
        
        AmapManger *strongSelf = weakSelf;
        [strongSelf addAnnotationToMapView:annotation];//将当前位置显示在地图上
    };
}
- (void)addAnnotationToMapView:(id<MAAnnotation>)annotation
{
   // [self.mapView addAnnotation:annotation];
    [self.mapView selectAnnotation:annotation animated:YES];
    [self.mapView setCenterCoordinate:annotation.coordinate animated:YES];
}

#pragma mark - MAMapView Delegate 描点回调
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation
{
    if ([annotation.title isEqualToString:@"当前位置"]) {
    //不需要描点
    }else if ([annotation.title isEqualToString:@"center"]) {
        static NSString *poiIdentifier = @"poiIdentifier";
        MAPinAnnotationView *poiAnnotationView = (MAPinAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:poiIdentifier];
        if (poiAnnotationView == nil)
        {
            poiAnnotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:poiIdentifier];
        }
        
        poiAnnotationView.canShowCallout = YES;
        poiAnnotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        
        return poiAnnotationView;
        
    } else {

            static NSString *reuseIndetifier = @"annotationReuseIndetifier";
            MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
            if (annotationView == nil)
            {
                annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation
                                                              reuseIdentifier:reuseIndetifier];
            }
            //[UIImage imageNamed:@"drivingIcon"]
            annotationView.image = [UIImage imageNamed:@"drivingIcon"];
            annotationView.canShowCallout   = YES;
            annotationView.draggable        = NO;
            //设置中心点偏移，使得标注底部中间点成为经纬度对应点
            annotationView.centerOffset = CGPointMake(0, -18);
            return annotationView;
    }
    
    return nil;
}

#pragma mark ---- search
///多条件搜索
- (void)searchhWithCity:(NSString *)city {
    AMapPOIKeywordsSearchRequest *request = [[AMapPOIKeywordsSearchRequest alloc] init];
    request.keywords            = @"驾校";//北京大学
    request.city                = city;
    request.types               = @"";//高等院校
    request.requireExtension    = YES;
    
    /*  搜索SDK 3.2.0 中新增加的功能，只搜索本城市的POI。*/
    request.cityLimit           = YES;
    request.requireSubPOIs      = YES;
    [self.search AMapPOIKeywordsSearch:request];
}
// 通过城市搜索
- (void)searchGeocodeWithCity:(NSString *)city { //
    AMapGeocodeSearchRequest *geo = [[AMapGeocodeSearchRequest alloc] init];
    geo.address = city;
    [self.search AMapGeocodeSearch:geo];
}

//获取城市坐标（搜索后获取坐标）
- (void)onGeocodeSearchDone:(AMapGeocodeSearchRequest *)request response:(AMapGeocodeSearchResponse *)response
{
    if (response.geocodes.count == 0)
    {
        return;
    }
    
    NSMutableArray *annotations = [NSMutableArray array];
    [response.geocodes enumerateObjectsUsingBlock:^(AMapGeocode *obj, NSUInteger idx, BOOL *stop) {
        GeocodeAnnotation *geocodeAnnotation = [[GeocodeAnnotation alloc] initWithGeocode:obj];
        
        [annotations addObject:geocodeAnnotation];
    }];
    AMapGeocode *geo = response.geocodes[0];
    self.pointBlock(geo);
    
    //将选中城市中心描点
    MAPointAnnotation *annotation = [[MAPointAnnotation alloc] init];
    CLLocation *location = [[CLLocation alloc]initWithLatitude:geo.location.latitude longitude:geo.location.longitude];
    [annotation setCoordinate:location.coordinate];
    annotation.title = @"center";
    [self.mapView addAnnotation:annotation]; //将中心位置显示在地图上
//    [self.mapView selectAnnotation:annotation animated:YES]; //设置点击大头针后的效果
    [self.mapView setCenterCoordinate:annotation.coordinate animated:YES]; //设置此为中心
}

//高德搜索地点后回调
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response
{
    if (response.pois.count == 0)
    {
        return;
    }
    if (response.pois.count == 0)
    {
        return;
    }
    NSMutableArray *poiAnnotations = [NSMutableArray arrayWithCapacity:response.pois.count];
    [response.pois enumerateObjectsUsingBlock:^(AMapPOI *obj, NSUInteger idx, BOOL *stop) {
        [poiAnnotations addObject:[[POIAnnotation alloc] initWithPOI:obj]];
        
    }];
   //解析response获取POI信息，具体解析见 Demo
   /* 将结果以annotation的形式加载到地图上. */
    [self.mapView addAnnotations:poiAnnotations];

    /* 如果只有一个结果，设置其为中心点. */
    if (poiAnnotations.count == 1)
    {
        [self.mapView setCenterCoordinate:[poiAnnotations[0] coordinate]];
    }
    /* 如果有多个结果, 设置地图使所有的annotation都可见. */
    else
    {
        [self.mapView showAnnotations:poiAnnotations animated:NO];
    }
}

// 将一个数组中的点显示在地图上
- (void)tracingPointWithAry:(NSArray *)pointAry {
    poiAnnotations = [NSMutableArray arrayWithCapacity:pointAry.count];
    [pointAry enumerateObjectsUsingBlock:^(AMapPOI *obj, NSUInteger idx, BOOL *stop) {
        [poiAnnotations addObject:[[POIAnnotation alloc] initWithPOI:obj]];
    }];
    /* 将结果以annotation的形式加载到地图上. */
    [self.mapView addAnnotations:poiAnnotations];
    if (poiAnnotations.count == 1) { /* 如果只有一个结果，设置其为中心点. */
        [self.mapView setCenterCoordinate:[poiAnnotations[0] coordinate]];
    } else { /* 如果有多个结果, 设置地图使所有的annotation都可见. */
//        [self.mapView showAnnotations:poiAnnotations animated:NO];
    }
    [self.mapView setZoomLevel:11.0 animated:NO];
}
- (void)selectPointWithName:(NSString *)name {
    for (POIAnnotation *anno in poiAnnotations) {
        if ([anno.title isEqualToString:name]) {
            [self addAnnotationToMapView:anno];
        }
    }
}
- (void)dealloc
{
    [self cleanUpAction];
    self.completionBlock = nil;
}
@end
